#pragma once

#include "llvm/Support/SourceMgr.h"
#include "llvm/Support/SMLoc.h"
#include "llvm/Support/FormatVariadic.h"

namespace diag
{
    enum
    {
#define DIAG(ID, KIND, MSG) ID,
#include "diag.inc"
    };
};

class DiagEngine
{
public:
    DiagEngine(llvm::SourceMgr &mgr) : mgr(mgr) {}

    template <typename... Args>                                 // 定义一个可变参数
    void Report(llvm::SMLoc loc, unsigned diagID, Args... args) // 传入这个可变参数
    {
        // 通过 diagID 可以获得 kind 和 msg
        auto kind = GetDiagKind(diagID);
        const char *fmt = GetDiagMsg(diagID);
        auto f = llvm::formatv(fmt, std::forward<Args>(args)...).str();
        mgr.PrintMessage(loc, kind, f);

        if (kind == llvm::SourceMgr::DK_Error)
        {
            exit(1);
        }
    }

private:
    llvm::SourceMgr::DiagKind GetDiagKind(unsigned id);
    const char *GetDiagMsg(unsigned id);

private:
    llvm::SourceMgr &mgr;
};